/*
 * CAttackChance.java
 *
 * Copyright (c) 2009 Giles Millward (Manigra). All rights reserved.
 *
 * This file is part of JRogueDPS.
 *
 * JRogueDPS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JRogueDPS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JRogueDPS.  If not, see <http://www.gnu.org/licenses/>.
 */
package dpssystem;

import java.util.Random;

/**
 *
 * @author gmillward
 */
public class CAttackChance {

    Random m_rng;
    boolean m_surpriseAttacks = false;

    public enum HitType {

        MISS, DODGE, PARRY, GLANCING, BLOCK, CRIT, NORMAL, RESIST
    };

    CAttackChance(CSim p_sim, Random p_rng)
    {
        m_rng = p_rng;
        if (p_sim.m_dpsInterface.m_talents.getSurpriseAttacks() != 0)
        {
            m_surpriseAttacks = true;
        }
    }

    public HitType getWhiteAttackType(double p_hit, double p_expertise, double p_crit) {

        double l_roll = m_rng.nextDouble();
        double l_hitTable = Math.max(0.27 - p_hit, 0);

        if (l_roll <= l_hitTable) {
            return HitType.MISS;
        }

        // Dodge
        l_hitTable += Math.max(0.0625 - p_expertise, 0);

        if (l_roll <= l_hitTable) {
            return HitType.DODGE;
        }

        // Glancing Blow
        l_hitTable += 0.24;
        if (l_roll <= l_hitTable) {
            return HitType.GLANCING;
        }

        // Critical Strike
        l_hitTable += p_crit;
        if (l_roll <= l_hitTable) {
            return HitType.CRIT;
        }

        // Normal
        return HitType.NORMAL;
    }

    public HitType getSpecialAttackHit(double p_hit, double p_expertise) {
        double l_roll = m_rng.nextDouble();
        double l_hitTable = Math.max(0.05 - p_hit, 0);
        if (l_roll <= l_hitTable) {
            return HitType.MISS;
        }

        // Dodge
        l_hitTable += Math.max(0.065 - p_expertise, 0);
        if (l_roll <= l_hitTable) {
            return HitType.DODGE;
        }

        // Hit the mob
        return HitType.NORMAL;
    }

    public HitType getFinisherAttackHit(double p_hit, double p_expertise) {
        double l_roll = m_rng.nextDouble();
        double l_hitTable = Math.max(0.05 - p_hit, 0);
        if (l_roll <= l_hitTable) {
            return HitType.MISS;
        }

        if (m_surpriseAttacks)
        {
            // Ignore dodge for finishers
            return HitType.NORMAL;
        }

        // Dodge
        l_hitTable += Math.max(0.065 - p_expertise, 0);
        if (l_roll <= l_hitTable) {
            return HitType.DODGE;
        }

        // Hit the mob
        return HitType.NORMAL;
    }

    public HitType getSpecialAttackCrit(double p_crit) {
        return ((m_rng.nextDouble() <= p_crit) ? HitType.CRIT:HitType.NORMAL);
    }

    public HitType getSpellHit(double p_hit)
    {
        return ((m_rng.nextDouble() <= Math.max(0.0, 0.17 - p_hit)) ? HitType.MISS:HitType.NORMAL);
    }

    public HitType getSpellHit(double p_hit, double p_crit) {
        HitType l_hitType = getSpellHit(p_hit);
        if (l_hitType == HitType.NORMAL)
        {
            return ((m_rng.nextDouble() <= p_crit) ? HitType.CRIT:HitType.NORMAL);
        }

        return l_hitType;
    }

}
